﻿using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using SFmpqapi;
using BLP2API;
using System.Diagnostics;
using System.Text.RegularExpressions;
 
namespace PACKETPARSERMAX20.WinUI
{
    public class MyViewer : System.Windows.Forms.PictureBox
    {
        private class clsMinimap
        {
            public string filename = null;
            public Texture texture = null;
            public bool cache = false;
            public bool dxt1 = false;
        }

        private class clsArea
        {
            public string area = "";
            public clsMinimap[,] minimaps = new clsMinimap[64, 64];
        }



        // Our global variables for this project
        Device device = null; // Our rendering device
        VertexBuffer vbMonster = null;
        VertexBuffer vbPlayer = null;
        VertexBuffer vbWeed = null;
        VertexBuffer vbMine = null;
        VertexBuffer vbObject = null;
        VertexBuffer vbMinimap = null;
        Microsoft.DirectX.Direct3D.Font font;

        // From WoW
        float mapSize = ((64 * 16) * ((150.0f / 36.0f) * 8));
        float tileSize = 150.0f / 36.0f * 8 * 16;

        float scale = 2;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;
  
        public MyViewer()
        {
            //InitializeComponent();
            InitializeGraphics();
        }
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        //#region Windows Form Designer generated code
        ///// <summary>
        ///// Required method for Designer support - do not modify
        ///// the contents of this method with the code editor.
        ///// </summary>
        //private void InitializeComponent()
        //{
        //    this.SuspendLayout();
        //    // 
        //    // frmViewer
        //    // 
        //    this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
        //    this.BackColor = System.Drawing.Color.Black;
        //    this.ClientSize = new System.Drawing.Size(300, 300);
        //    this.KeyPreview = true;
        //    this.Name = "frmViewer";
        //    this.Load += new System.EventHandler(this.frmMain_Load);
        //    this.Closing += new System.ComponentModel.CancelEventHandler(this.frmMain_Closing);
        //    this.ResumeLayout(false);

        //}
        //#endregion

        private delegate void DelUpdateText();

        private ArrayList minimapCache = new ArrayList();
        private Hashtable areas = new Hashtable();

        public clsSettings settings;
    
  
        private bool mUpdating = false;
 
        #region "Viewer Methods and Functions"
        public bool InitializeGraphics()
        {
            try
            {
                // Now let's setup our D3D stuff
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;
                presentParams.SwapEffect = SwapEffect.Discard;

                device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
                device.DeviceReset += new System.EventHandler(this.OnResetDevice);
                this.OnCreateDevice(device, null);
                this.OnResetDevice(device, null);

                //font = new Microsoft.DirectX.Direct3D.Font(device, new System.Drawing.Font("Verdana", 8f));
                font = new Microsoft.DirectX.Direct3D.Font(device, new System.Drawing.Font("Arial", 8f));

                return true;
            }
            catch (DirectXException)
            {
                return false;
            }

        }
        public void OnCreateDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;

            // Now Create the VB
            vbMonster = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbMonster.Created += new System.EventHandler(this.OnCreateVBMonster);
            this.OnCreateVBMonster(vbMonster, null);

            // Now Create the VB
            vbPlayer = new VertexBuffer(typeof(CustomVertex.PositionColored), 6, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbPlayer.Created += new System.EventHandler(this.OnCreateVBPlayer);
            this.OnCreateVBPlayer(vbPlayer, null);

            // Now Create the VB
            vbWeed = new VertexBuffer(typeof(CustomVertex.PositionColored), 12, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbWeed.Created += new System.EventHandler(this.OnCreateVBWeed);
            this.OnCreateVBWeed(vbWeed, null);

            // Now Create the VB
            vbMine = new VertexBuffer(typeof(CustomVertex.PositionColored), 15, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbMine.Created += new System.EventHandler(this.OnCreateVBMine);
            this.OnCreateVBMine(vbMine, null);

            // Now Create the VB
            vbObject = new VertexBuffer(typeof(CustomVertex.PositionColored), 6, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
            vbObject.Created += new System.EventHandler(this.OnCreateVBObject);
            this.OnCreateVBObject(vbObject, null);

            // Now Create the VB
            vbMinimap = new VertexBuffer(typeof(CustomVertex.PositionNormalTextured), 6, dev, 0, CustomVertex.PositionNormalTextured.Format, Pool.Default);
            vbMinimap.Created += new System.EventHandler(this.OnCreateVBMinimap);
            this.OnCreateVBMinimap(vbMinimap, null);
        }
        public void OnResetDevice(object sender, EventArgs e)
        {
            Device dev = (Device)sender;

            // Turn off culling, so we see the front and back of the triangle
            dev.RenderState.CullMode = Cull.None;

            // Turn off D3D lighting, since we are providing our own vertex colors
            dev.RenderState.Lighting = false;

            // Turn on the ZBuffer
            dev.RenderState.ZBufferEnable = true;

            dev.RenderState.AntiAliasedLineEnable = true;
        }
        private Vector3 ComputeNormal(Vector3 v1, Vector3 v2, Vector3 v3)
        {
            Vector3 N = Vector3.Cross(Vector3.Subtract(v2, v1), Vector3.Subtract(v3, v1));
            return Vector3.Normalize(N);
        }
        public void OnCreateVBMinimap(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])vb.Lock(0, 0);

            Vector3 v1 = new Vector3(-((float)(tileSize) / 2), -((float)(tileSize) / 2), 0);
            Vector3 v2 = new Vector3(((float)(tileSize) / 2), -((float)(tileSize) / 2), 0);
            Vector3 v3 = new Vector3(-((float)(tileSize) / 2), ((float)(tileSize) / 2), 0);
            Vector3 n = ComputeNormal(v1, v2, v3);

            verts[0] = new CustomVertex.PositionNormalTextured(v1, n, 0, 0);
            verts[1] = new CustomVertex.PositionNormalTextured(v2, n, 1, 0);
            verts[2] = new CustomVertex.PositionNormalTextured(v3, n, 0, 1);

            v1 = new Vector3(((float)(tileSize) / 2), ((float)(tileSize) / 2), 0);
            v2 = new Vector3(-((float)(tileSize) / 2), ((float)(tileSize) / 2), 0);
            v3 = new Vector3(((float)(tileSize) / 2), -((float)(tileSize) / 2), 0);
            n = ComputeNormal(v1, v2, v3);
            verts[3] = new CustomVertex.PositionNormalTextured(v1, n, 1, 1);
            verts[4] = new CustomVertex.PositionNormalTextured(v2, n, 0, 1);
            verts[5] = new CustomVertex.PositionNormalTextured(v3, n, 1, 0);

            vb.Unlock();
        }
        public void OnCreateVBObject(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = -1.0f; verts[0].Y = -1.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = 1.0f; verts[1].Y = -1.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = -1.0f; verts[2].Y = 1.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            verts[3].X = 1.0f; verts[3].Y = 1.0f; verts[3].Z = 0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[4].X = 1.0f; verts[4].Y = -1.0f; verts[4].Z = 0f; verts[4].Color = System.Drawing.Color.White.ToArgb();
            verts[5].X = -1.0f; verts[5].Y = 1.0f; verts[5].Z = 0f; verts[5].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        public void OnCreateVBMine(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = -2.0f; verts[0].Y = 0.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = -2.0f; verts[1].Y = 1.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = 0.0f; verts[2].Y = 0.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            verts[3].X = 2.0f; verts[3].Y = 0.0f; verts[3].Z = 0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[4].X = 2.0f; verts[4].Y = 1.0f; verts[4].Z = 0f; verts[4].Color = System.Drawing.Color.White.ToArgb();
            verts[5].X = 0.0f; verts[5].Y = 0.0f; verts[5].Z = 0f; verts[5].Color = System.Drawing.Color.White.ToArgb();

            verts[6].X = 2.0f; verts[6].Y = 1.0f; verts[6].Z = 0f; verts[6].Color = System.Drawing.Color.White.ToArgb();
            verts[7].X = 1.0f; verts[7].Y = 2.0f; verts[7].Z = 0f; verts[7].Color = System.Drawing.Color.White.ToArgb();
            verts[8].X = 0.0f; verts[8].Y = 0.0f; verts[8].Z = 0f; verts[8].Color = System.Drawing.Color.White.ToArgb();

            verts[9].X = -2.0f; verts[9].Y = 1.0f; verts[9].Z = 0f; verts[9].Color = System.Drawing.Color.White.ToArgb();
            verts[10].X = -1.0f; verts[10].Y = 2.0f; verts[10].Z = 0f; verts[10].Color = System.Drawing.Color.White.ToArgb();
            verts[11].X = 0.0f; verts[11].Y = 0.0f; verts[11].Z = 0f; verts[11].Color = System.Drawing.Color.White.ToArgb();

            verts[12].X = -1.0f; verts[12].Y = 2.0f; verts[12].Z = 0f; verts[12].Color = System.Drawing.Color.White.ToArgb();
            verts[13].X = 1.0f; verts[13].Y = 2.0f; verts[13].Z = 0f; verts[13].Color = System.Drawing.Color.White.ToArgb();
            verts[14].X = 0.0f; verts[14].Y = 0.0f; verts[14].Z = 0f; verts[14].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        public void OnCreateVBWeed(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = 0.0f; verts[0].Y = 2.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = -1.0f; verts[1].Y = 0.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = 1.0f; verts[2].Y = 0.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            verts[3].X = 0.0f; verts[3].Y = -2.0f; verts[3].Z = 0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[4].X = -1.0f; verts[4].Y = 0.0f; verts[4].Z = 0f; verts[4].Color = System.Drawing.Color.White.ToArgb();
            verts[5].X = 1.0f; verts[5].Y = 0.0f; verts[5].Z = 0f; verts[5].Color = System.Drawing.Color.White.ToArgb();

            verts[6].X = -2.0f; verts[6].Y = 0.0f; verts[6].Z = 0f; verts[6].Color = System.Drawing.Color.White.ToArgb();
            verts[7].X = 0.0f; verts[7].Y = 1.0f; verts[7].Z = 0f; verts[7].Color = System.Drawing.Color.White.ToArgb();
            verts[8].X = 0.0f; verts[8].Y = -1.0f; verts[8].Z = 0f; verts[8].Color = System.Drawing.Color.White.ToArgb();

            verts[9].X = 2.0f; verts[9].Y = 0.0f; verts[9].Z = 0f; verts[9].Color = System.Drawing.Color.White.ToArgb();
            verts[10].X = 0.0f; verts[10].Y = 1.0f; verts[10].Z = 0f; verts[10].Color = System.Drawing.Color.White.ToArgb();
            verts[11].X = 0.0f; verts[11].Y = -1.0f; verts[11].Z = 0f; verts[11].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        public void OnCreateVBPlayer(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = -2.0f; verts[0].Y = -2.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = 0.0f; verts[1].Y = -1.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = 0.0f; verts[2].Y = 2.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            verts[3].X = 2.0f; verts[3].Y = -2.0f; verts[3].Z = 0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[4].X = 0.0f; verts[4].Y = -1.0f; verts[4].Z = 0f; verts[4].Color = System.Drawing.Color.White.ToArgb();
            verts[5].X = 0.0f; verts[5].Y = 2.0f; verts[5].Z = 0f; verts[5].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        public void OnCreateVBMonster(object sender, EventArgs e)
        {
            VertexBuffer vb = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = (CustomVertex.PositionColored[])vb.Lock(0, 0);

            verts[0].X = -1.0f; verts[0].Y = -2.0f; verts[0].Z = 0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[1].X = 1.0f; verts[1].Y = -2.0f; verts[1].Z = 0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[2].X = 0.0f; verts[2].Y = 2.0f; verts[2].Z = 0f; verts[2].Color = System.Drawing.Color.White.ToArgb();

            vb.Unlock();
        }
        #endregion
        private bool mbool = true;
     

        //private Hashtable mAreas = new Hashtable();
        private void frmMain_Load(object sender, EventArgs e)
        {
            settings = new clsSettings();
            settings.LoadDefaults();
            
            //System.Xml.XmlDocument tdom = new XmlDocument();
            //tdom.Load(".\\areas.xml");

            //foreach (System.Xml.XmlElement telem in tdom.DocumentElement.SelectNodes("area"))
            //{
            //    mAreas[int.Parse(telem.Attributes["id"].Value)] = telem.Attributes["name"].Value;
            //}

            //if (File.Exists("SERFLITEMAX20.Viewer.xml"))
            //{
            //    try
            //    {
            //        XmlTextReader xr = new XmlTextReader("SERFLITEMAX20.Viewer.xml");
            //        XmlSerializer xs = new XmlSerializer(settings.GetType());
           
            //        settings = (clsSettings)xs.Deserialize(xr);
            //        xr.Close();
            //    }
            //    catch(System.InvalidOperationException ex)
            //    {
                    settings = new clsSettings();
                    settings.LoadDefaults();
            //    }
            //}

            settings.UpdateHashtable();
            //this.TopMost = settings.StayOnTop;
            //settings.RotateMap = true;
            BuildAreas();


        }

        //private void UpdateText()
        //{
        //    this.Text = "Received Count: " + mMain.CurrentObjectCount.ToString() +
        //    ", Received Size: " + mMain.CurrentSize.ToString();
        //    if (mMain.Player != null)
        //    {
        //        this.Text += ", Facing:" + mMain.Player.Facing.ToString() +
        //        ", X:" + mMain.Player.X.ToString() +
        //        ", Y:" + mMain.Player.Y.ToString() +
        //        ", Z:" + mMain.Player.Z.ToString();
        //    }
        //}

        private void frmMain_Closing(object sender, CancelEventArgs e)
        {

            settings.FormX = Left;
            settings.FormY = Top;
            settings.FormWidth = Width;
            settings.FormHeight = Height;

            XmlTextWriter xw = new XmlTextWriter("SERFLITEMAX20.Viewer.xml", System.Text.Encoding.ASCII);
            XmlSerializer xs = new XmlSerializer(settings.GetType());
            xs.Serialize(xw, settings);
            xw.Close();
        }
        
        //private void OnUpdate(string message)
        //{

        //    if (!mUpdating)
        //    {
        //        Main tsender = new Main();
        //        //message = message.Substring(0, message.IndexOf("</Main>") + "</Main>".Length);
        //        tsender.InitializeFromXML(message);
        //        OnUpdateMain(tsender);
        //    }
        //}


        //private void GetUnitDisplayData(ViewObject pObject, ref clsDisplayItem pDisplayItem, ref VertexBuffer pBuffer, ref int pVertexCount, ref bool pRotate, ref string pName, ref bool pVisible)
        //{
        //    pVisible = true;
        //    pRotate = true;
        //    pBuffer = vbMonster;
        //    pVertexCount = 1;
        //    pName = pObject.name + "(" + pObject.level.ToString() + ")";

        //    if (pObject.isDead)
        //    {
        //        pDisplayItem = settings.GetDisplayItem("[NPC's: Dead]", null);
        //    }
        //    else
        //    {
        //        switch (pObject.unitReaction)
        //        {
        //            case 1:
        //                pVisible = IsToggleView(ToggleView.unitenemy);
        //                pDisplayItem = settings.GetDisplayItem("[NPC's: Agressive]", null);
        //                break;

        //            case 3:
        //                pVisible = IsToggleView(ToggleView.unitsneutral);
        //                pDisplayItem = settings.GetDisplayItem("[NPC's: Neutral]", null);
        //                break;

        //            case 4:
        //                pVisible = IsToggleView(ToggleView.unitsfreindly);
        //                pDisplayItem = settings.GetDisplayItem("[NPC's: Friendly]", null);
        //                break;
        //        }
        //    }

        //}

        //private void GetPlayerDisplayData(ViewObject pObject, ref clsDisplayItem pDisplayItem, ref VertexBuffer pBuffer, ref int pVertexCount, ref bool pRotate, ref string pName, ref bool pVisible)
        //{

        //    pRotate = true;
        //    pBuffer = vbPlayer;
        //    pVertexCount = 2;
        //    pDisplayItem = settings.GetDisplayItem("[Player]", null);
        //    pName = pObject.name + "(" + pObject.level.ToString() + ")";
        //    pVisible = IsToggleView(ToggleView.alliedunits);

        //    if (pObject.isDead)
        //    {
        //        pDisplayItem = settings.GetDisplayItem("[Players: Dead]", null);
        //    }
        //    else
        //    {

        //        if (pObject.unitReaction == 1 && (pObject.flags & 512) > 0)
        //        {
        //            pDisplayItem = settings.GetDisplayItem("[Players: Agressive]", pDisplayItem);
        //            pVisible = IsToggleView(ToggleView.enemyplayersflaged);
        //        }
        //        else
        //        {

        //            if (pObject.unitReaction == 1)
        //            {
        //                pVisible = IsToggleView(ToggleView.enemyplayersunflaged);
        //                pDisplayItem = settings.GetDisplayItem("[Players: Neutral]", pDisplayItem);
        //            }

        //        }


        //        //switch (pObject.UnitReaction)
        //        //{
        //        //    case 1:

        //        //        pDisplayItem = settings.GetDisplayItem("[Players: Agressive]", pDisplayItem);
        //        //        break;

        //        //    case 3:
        //        //        pDisplayItem = settings.GetDisplayItem("[Players: Neutral]", pDisplayItem);
        //        //        break;

        //        //    case 4:
        //        //        pDisplayItem = settings.GetDisplayItem("[Players: Friendly]", pDisplayItem);
        //        //        break;
        //        //}
        //    }


        //}

        //private void GetDynamiDisplayData(ViewObject pObject, ref clsDisplayItem pDisplayItem, ref VertexBuffer pBuffer, ref int pVertexCount, ref bool pRotate, ref string pName, ref bool pVisible)
        //{

        //    pRotate = true;
        //    pBuffer = vbPlayer;
        //    pVertexCount = 2;
        //    pDisplayItem = settings.GetDisplayItem("[Object: Dynamic]", null);
        //    pName = pObject.name;
        //    pVisible = true;




        //}


        //private void GetGameObjectDisplayData(ViewObject pObject, ref clsDisplayItem pDisplayItem, ref VertexBuffer pBuffer, ref int pVertexCount, ref bool pRotate, ref string pName, ref bool pVisible)
        //{
        //    pVisible = true;
        //    pName = pObject.name;

        //    if (pObject.isMiningNode)
        //    {
        //        pBuffer = vbMine;
        //        pVertexCount = 5;
        //        // pVisible = IsToggleView(ToggleView.miniralobject);
        //        pDisplayItem = settings.GetDisplayItem("[Object: Metal Ore]", null);
        //    }
        //    else if (pObject.isWeedNode)
        //    {
        //        pBuffer = vbWeed;
        //        pVertexCount = 4;
        //        //pVisible = IsToggleView(ToggleView.bushobjects);
        //        pDisplayItem = settings.GetDisplayItem("[Object: Weed]", null);
        //    }
        //    else if (pObject.isTreasureNode)
        //    {
        //        pBuffer = vbMine;
        //        pVertexCount = 5;
        //        // pVisible = IsToggleView(ToggleView.treasureobjects);
        //        pDisplayItem = settings.GetDisplayItem("[Object: Treasure]", null);
        //    }
        //    else if (pObject.isFishingNode)
        //    {
        //        pBuffer = vbWeed;
        //        pVertexCount = 4;
        //        //pVisible = IsToggleView(ToggleView.fishobjects);
        //        pDisplayItem = settings.GetDisplayItem("[Object: Fish]", null);
        //        //}
        //        //else
        //        //{
        //        //pVisible = IsToggleView(ToggleView.questobjects);
        //    }
        //}
        public void UpdateViewer(object sender)
        {
             //this.InvokeRequired 
            if (sender is PACKETPARSERMAX20.CORE.WoWCore)
            {
                OnUpdateMain((PACKETPARSERMAX20.CORE.WoWCore)sender);
            }
        }
        private void OnUpdateMain(PACKETPARSERMAX20.CORE.WoWCore pCore)
        {
            if (!mUpdating)
            {
                if (device == null)
                    return;

                if (pCore.Player == null)
                    return;


                mUpdating = true;

                //Clear the backbuffer to a black color
                device.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0);

                float camDist = 100000.0F;
                Vector3 camPos = new Vector3(0.0F, 0.0F, camDist);
                Vector3 camTarg = new Vector3(0.0F, 0.0F, 0.0F);
                Vector3 camUpVec = new Vector3(0.0F, -1.0F, 0.0F);

                Matrix rotMap = Matrix.RotationY(180 * 0.01745329f) * Matrix.RotationX(180 * 0.01745329f);

                if (settings.RotateMap)
                    rotMap *= Matrix.RotationZ(360 * 0.01745329f - pCore.Player.O);

                camPos.TransformCoordinate(rotMap);
                camTarg.TransformCoordinate(rotMap);
                camUpVec.TransformCoordinate(rotMap);

                //camTarg.Add(new Vector3(pCore.Player.X, pCore.Player.Y, pCore.Player.Z));
                //camPos.Add(new Vector3(pCore.Player.X, pCore.Player.Y, pCore.Player.Z));

                camTarg.Add(new Vector3(pCore.Player.Y, pCore.Player.X, pCore.Player.Z));
                camPos.Add(new Vector3(pCore.Player.Y, pCore.Player.X, pCore.Player.Z));

                device.Transform.View = Matrix.LookAtLH(camPos, camTarg, camUpVec);
                device.Transform.Projection = Matrix.PerspectiveLH(Width / (camDist * scale), Height / (camDist * scale), 1, 1000000);

                //this.Text = "Current Continent: " + sender.CurrentContinent.ToString() + ", Current WorldFrame: " + sender.CurrentWorldFrame.ToString();
                //Begin the scene
                device.BeginScene();

                if (mbool && settings.ShowMinimap)
                    DrawMinimap(pCore.Player.Y, pCore.Player.X, (int)pCore.MapID);

                foreach (PACKETPARSERMAX20.CORE.WoWObjectBase obj in pCore.ObjList.Values)
                {
                    //if (obj == pCore.Player) { continue; }
                    if (obj.typeid == PACKETPARSERMAX20.CORE.TypeID.TYPEID_DYNAMICOBJECT || obj.typeid == PACKETPARSERMAX20.CORE.TypeID.TYPEID_UNIT || obj.typeid == PACKETPARSERMAX20.CORE.TypeID.TYPEID_PLAYER || obj.typeid == PACKETPARSERMAX20.CORE.TypeID.TYPEID_GAMEOBJECT || obj.typeid == PACKETPARSERMAX20.CORE.TypeID.TYPEID_CORPSE)
                    {

                        bool rotate = true;
                        int noVertexs = 4;
                        VertexBuffer vBuffer = vbObject;
                        if (obj.typeid == PACKETPARSERMAX20.CORE.TypeID.TYPEID_PLAYER)
                        {
                            vBuffer = vbPlayer;
                        }
                        else if (obj.typeid == PACKETPARSERMAX20.CORE.TypeID.TYPEID_UNIT)
                        {
                            vBuffer = vbMonster;
                        }
                        else if (obj.typeid == PACKETPARSERMAX20.CORE.TypeID.TYPEID_GAMEOBJECT)
                        {
                            vBuffer = vbObject;
                      //obj.UpdateValues["OBJECT_FIELD_TYPE"]
                             
                            

                        }

                        string name = obj.Name;
                  
                        int tcolor = Color.White.ToArgb() ;

                        //switch (obj.type)
                        //{
                        //    case enObjectTypes.Dynamic: GetDynamiDisplayData(obj, ref di, ref vBuffer, ref  noVertexs, ref rotate, ref name, ref tVisible); break;
                        //    case enObjectTypes.Unit: GetUnitDisplayData(obj, ref di, ref vBuffer, ref  noVertexs, ref rotate, ref name, ref tVisible); break;
                        //    case enObjectTypes.Player: GetPlayerDisplayData(obj, ref di, ref vBuffer, ref  noVertexs, ref rotate, ref name, ref tVisible); break;
                        //    case enObjectTypes.GameObject: GetGameObjectDisplayData(obj, ref di, ref vBuffer, ref  noVertexs, ref rotate, ref name, ref tVisible); break;
                        //}

                        float iscale = 2 * (2 / scale);
                        Vector3 pos = new Vector3(obj.Y, obj.X, obj.Z);
                        //Vector3 pos = new Vector3(obj.X, obj.Y, obj.Z);

                        device.Transform.World = Matrix.Scaling(iscale, iscale, iscale);

                        if (rotate)
                            device.Transform.World *= Matrix.RotationZ(360 * 0.01745329f - obj.O);
                        else if (settings.RotateMap)
                            device.Transform.World *= Matrix.RotationZ(360 * 0.01745329f - pCore.Player.O );

                        device.Transform.World *= Matrix.Translation(pos);

                        device.RenderState.TextureFactor = tcolor;


                        device.TextureState[0].ColorOperation = TextureOperation.Modulate;
                        device.TextureState[0].ColorArgument0 = TextureArgument.TextureColor;
                        device.TextureState[0].ColorArgument1 = TextureArgument.TFactor;

                        device.VertexFormat = CustomVertex.PositionColored.Format;
                        device.SetTexture(0, null);

                        device.SetStreamSource(0, vBuffer, 0);
                        device.DrawPrimitives(PrimitiveType.TriangleList, 0, noVertexs);

                        pos = Vector3.Project(new Vector3(0, 0, 0), device.Viewport, device.Transform.Projection, device.Transform.View, device.Transform.World);

                        if (name != null)
                        {
                            //font.DrawText(null, name, (int)pos.Y + 10, (int)pos.X - 4, tcolor);
                            font.DrawText(null, name, (int)pos.X + 10, (int)pos.Y - 4, tcolor);
                             
                        }


                    }
                }

                device.EndScene();
                device.Present();
            }

            mUpdating = false;
        }

    
 

        
        private void DrawMinimap(float PosX, float PosY, int mapid)
        {
            float absCoordX = (mapSize / 2) - PosX + tileSize;
            float absCoordY = (mapSize / 2) - PosY + tileSize;

            int tileX = (int)(absCoordX / tileSize) - 1;
            int tileY = (int)(absCoordY / tileSize) - 1;

            foreach (clsMinimap minimap in minimapCache)
                minimap.cache = false;


            string area = "";

            switch (mapid)
            {
                case 0: area = "Azeroth"; break;
                case 1: area = "Kalimdor"; break;
                case 13: area = "test"; break;
                case 25: area = "ScottTest"; break;
                case 29: area = "Test"; break;
                case 30: area = "PVPZone01"; break;
                case 33: area = "Shadowfang"; break;
                case 34: area = "StormwindJail"; break;
                case 35: area = "StormwindPrison"; break;
                case 36: area = "DeadminesInstance"; break;
                case 37: area = "PVPZone02"; break;
                case 42: area = "Collin"; break;
                case 43: area = "WailingCaverns"; break;
                case 44: area = "Monastery"; break;
                case 47: area = "RazorfenKraulInstance"; break;
                case 48: area = "Blackfathom"; break;
                case 70: area = "Uldaman"; break;
                case 90: area = "GnomeragonInstance"; break;
                case 109: area = "SunkenTemple"; break;
                case 129: area = "RazorfenDowns"; break;
                case 169: area = "EmeraldDream"; break;
                case 189: area = "MonasteryInstances"; break;
                case 209: area = "TanarisInstance"; break;
                case 229: area = "BlackRockSpire"; break;
                case 230: area = "BlackrockDepths"; break;
                case 249: area = "OnyxiaLairInstance"; break;
                case 269: area = "CavernsOfTime"; break;
                case 289: area = "SchoolofNecromancy"; break;
                case 309: area = "Zul'gurub"; break;
                case 329: area = "Stratholme"; break;
                case 349: area = "Mauradon"; break;
                case 369: area = "DeeprunTram"; break;
                case 389: area = "OrgrimmarInstance"; break;
                case 409: area = "MoltenCore"; break;
                case 429: area = "DireMaul"; break;
                case 449: area = "AlliancePVPBarracks"; break;
                case 450: area = "HordePVPBarracks"; break;
                case 451: area = "development"; break;
                case 469: area = "BlackwingLair"; break;
                case 489: area = "PVPZone03"; break;
                case 509: area = "AhnQiraj"; break;
                case 529: area = "PVPZone04"; break;
                case 530: area = "Expansion01"; break;
                case 531: area = "AhnQirajTemple"; break;
                case 532: area = "Karazahn"; break;
                case 533: area = "Stratholme Raid"; break;
                case 534: area = "HyjalPast"; break;
                case 540: area = "HellfireMilitary"; break;
                case 542: area = "HellfireDemon"; break;
                case 543: area = "HellfireRampart"; break;
                case 544: area = "HellfireRaid"; break;
                case 545: area = "CoilfangPumping"; break;
                case 546: area = "CoilfangMarsh"; break;
                case 547: area = "CoilfangDraenei"; break;
                case 548: area = "CoilfangRaid"; break;
                case 550: area = "TempestKeepRaid"; break;
                case 552: area = "TempestKeepArcane"; break;
                case 553: area = "TempestKeepAtrium"; break;
                case 554: area = "TempestKeepFactory"; break;
                case 555: area = "AuchindounShadow"; break;
                case 556: area = "AuchindounDemon"; break;
                case 557: area = "AuchindounEthereal"; break;
                case 558: area = "AuchindounDraenei"; break;
                case 559: area = "PVPZone05"; break;
                case 560: area = "HillsbradPast"; break;
                case 562: area = "bladesedgearena"; break;
                case 564: area = "BlackTemple"; break;
                case 565: area = "GruulsLair"; break;
                case 566: area = "NetherstormBG"; break;
                case 568: area = "ZulAman"; break;
                case 572: area = "PVPLordaeron"; break;
                case 580: area = "SunwellPlateau"; break;
                case 582: area = "Transport176244"; break;
                case 584: area = "Transport176231"; break;
                case 585: area = "Sunwell5ManFix"; break;
                case 586: area = "Transport181645"; break;
                case 587: area = "Transport177233"; break;
                case 588: area = "Transport176310"; break;
                case 589: area = "Transport175080"; break;
                case 590: area = "Transport176495"; break;
                case 591: area = "Transport164871"; break;
                case 593: area = "Transport20808"; break;
                case 598: area = "Sunwell5Man"; break;

            }
            //if(mAreas.Contains( mMain.AreaID))
            //{
            //    area = (string)mAreas[mMain.AreaID];
            //}
            //switch (mapid)
            //{
            //    case 0: area = "Azeroth"; break;
            //    case 1: area = "Kalimdor"; break;
            //    case 13: area = "test"; break;
            //    case 25: area = "ScottTest"; break;
            //    case 29: area = "Test"; break;
            //    case 30: area = "PVPZone01"; break;
            //    case 33: area = "Shadowfang"; break;
            //    case 34: area = "StormwindJail"; break;
            //    case 35: area = "StormwindPrison"; break;
            //    case 36: area = "DeadminesInstance"; break;
            //    case 37: area = "PVPZone02"; break;
            //    case 42: area = "Collin"; break;
            //    case 43: area = "WailingCaverns"; break;
            //    case 44: area = "Monastery"; break;
            //    case 47: area = "RazorfenKraulInstance"; break;
            //    case 48: area = "Blackfathom"; break;
            //    case 70: area = "Uldaman"; break;
            //    case 90: area = "GnomeragonInstance"; break;
            //    case 109: area = "SunkenTemple"; break;
            //    case 129: area = "RazorfenDowns"; break;
            //    case 169: area = "EmeraldDream"; break;
            //    case 189: area = "MonasteryInstances"; break;
            //    case 209: area = "TanarisInstance"; break;
            //    case 229: area = "BlackRockSpire"; break;
            //    case 230: area = "BlackrockDepths"; break;
            //    case 249: area = "OnyxiaLairInstance"; break;
            //    case 269: area = "CavernsOfTime"; break;
            //    case 289: area = "SchoolofNecromancy"; break;
            //    case 309: area = "Zul'gurub"; break;
            //    case 329: area = "Stratholme"; break;
            //    case 349: area = "Mauradon"; break;
            //    case 369: area = "DeeprunTram"; break;
            //    case 389: area = "OrgrimmarInstance"; break;
            //    case 409: area = "MoltenCore"; break;
            //    case 429: area = "DireMaul"; break;
            //    case 449: area = "AlliancePVPBarracks"; break;
            //    case 450: area = "HordePVPBarracks"; break;
            //    case 451: area = "development"; break;
            //    case 469: area = "BlackwingLair"; break;
            //    case 489: area = "PVPZone03"; break;
            //    case 509: area = "AhnQiraj"; break;
            //    case 529: area = "PVPZone04"; break;
            //    case 530: area = "Expansion01"; break;
            //    case 531: area = "AhnQirajTemple"; break;
            //    case 532: area = "Karazahn"; break;
            //    case 533: area = "Stratholme Raid"; break;
            //    case 534: area = "HyjalPast"; break;
            //    case 540: area = "HellfireMilitary"; break;
            //    case 542: area = "HellfireDemon"; break;
            //    case 543: area = "HellfireRampart"; break;
            //    case 544: area = "HellfireRaid"; break;
            //    case 545: area = "CoilfangPumping"; break;
            //    case 546: area = "CoilfangMarsh"; break;
            //    case 547: area = "CoilfangDraenei"; break;
            //    case 548: area = "CoilfangRaid"; break;
            //    case 550: area = "TempestKeepRaid"; break;
            //    case 552: area = "TempestKeepArcane"; break;
            //    case 553: area = "TempestKeepAtrium"; break;
            //    case 554: area = "TempestKeepFactory"; break;
            //    case 555: area = "AuchindounShadow"; break;
            //    case 556: area = "AuchindounDemon"; break;
            //    case 557: area = "AuchindounEthereal"; break;
            //    case 558: area = "AuchindounDraenei"; break;
            //    case 559: area = "PVPZone05"; break;
            //    case 560: area = "HillsbradPast"; break;
            //    case 562: area = "bladesedgearena"; break;
            //    case 564: area = "BlackTemple"; break;
            //    case 565: area = "GruulsLair"; break;
            //    case 566: area = "NetherstormBG"; break;
            //    case 568: area = "ZulAman"; break;

            //}



            for (int x = tileX - settings.MinimapRadius; x <= (tileX + settings.MinimapRadius); x++)
                for (int y = tileY - settings.MinimapRadius; y <= (tileY + settings.MinimapRadius); y++)
                {
                    clsMinimap minimap = LoadMinimap(x, y, area);

                    if (minimap == null)
                        continue;

                    minimap.cache = true;
                    if (minimap.texture != null)
                    {
                        float mapX = -((x * tileSize) - (mapSize / 2)) - (tileSize / 2);
                        float mapY = -((y * tileSize) - (mapSize / 2)) - (tileSize / 2);

                        if (minimap.dxt1)
                            device.Transform.World = Matrix.RotationX(180 * 0.01745329f) * Matrix.RotationY(180 * 0.01745329f) * Matrix.Translation(mapX, mapY, -1000);
                        else
                            device.Transform.World = Matrix.RotationY(180 * 0.01745329f) * Matrix.Translation(mapX, mapY, -1000);

                        device.SetTexture(0, minimap.texture);
                        device.TextureState[0].ColorOperation = TextureOperation.Modulate;
                        device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
                        device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
                        device.TextureState[0].AlphaOperation = TextureOperation.Disable;

                        device.VertexFormat = CustomVertex.PositionNormalTextured.Format;

                        device.SetStreamSource(0, vbMinimap, 0);
                        device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
                    }
                }

            foreach (clsMinimap minimap in minimapCache)
                if (!minimap.cache)
                {
                    // Dont cache it anymore
                    if (minimap.texture != null)
                    {
                        minimap.texture.Dispose();
                        minimap.texture = null;
                    }
                }
        }

        private void GetMinimapTexture(clsMinimap minimap)
        {
            int hMPQ = 0;
            int hFile = 0;
            int FileSize = 0;
            int FileRead = 0;
            //"C:\\Program Files\\World of Warcraft\\Data\\texture.MPQ"
            if (SFmpq.SFileOpenArchive(".\\minimap.MPQ", 0, 0, ref hMPQ) != 1)
            {
                return;
            }

            //if( SFmpq.SFileOpenFileEx( hMPQ, "textures\\Minimap\\" + minimap.filename, 0, ref hFile) != 1)
            if (SFmpq.SFileOpenFileEx(hMPQ, minimap.filename, 0, ref hFile) != 1)
            {
                SFmpq.SFileCloseFile(hMPQ);
                return;
            }

            FileSize = SFmpq.SFileGetFileSize(hFile, ref FileSize);
            byte[] buffer = new byte[FileSize];

            //WoW.LogLine( "Reading texture.MPQ|textures\\Minimap\\{0}", minimap.filename);
            if (SFmpq.SFileReadFile(hFile, buffer, (uint)FileSize, ref FileRead, IntPtr.Zero) == 1)
            {
                //WoW.LogLine( "Parsing texture.MPQ|textures\\Minimap\\{0}", minimap.filename);

                minimap.dxt1 = true;
                MemoryStream ms = BLP2Parse.BLPtoDXT1(buffer);
                if (ms != null && ms.Length > 0x70)
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    try
                    {
                        minimap.texture = TextureLoader.FromStream(device, ms);
                        if (minimap.texture == null)
                            minimap.dxt1 = false;
                    }
                    catch
                    {
                        minimap.dxt1 = false;
                    }
                }

                if (!minimap.dxt1)
                {
                    ms = BLP2Parse.BLPtoTGA(buffer);
                    ms.Seek(0, SeekOrigin.Begin);
                    try
                    {
                        minimap.texture = TextureLoader.FromStream(device, ms);
                    }
                    catch
                    {
                    }
                }
            }
            else
            {
            }

            SFmpq.SFileCloseFile(hFile);
            SFmpq.SFileCloseArchive(hMPQ);

            return;
        }

        private clsMinimap LoadMinimap(int X, int Y, string Area)
        {
            if (X > 63 || Y > 63 || X < 0 || Y < 0)
                return null;

            clsArea area = (clsArea)areas[Area];
            if (area == null)
                return null;

            clsMinimap minimap = area.minimaps[X, Y];
            if (minimap != null && minimap.texture == null)
                GetMinimapTexture(minimap);

            return minimap;
        }

        private void BuildMinimapList(byte[] md5list)
        {
            MemoryStream src = new MemoryStream(md5list);
            StreamReader sr = new StreamReader(src);

            Regex map = new Regex(@"^.[^\\]+\\[a-z,A-Z]+([0-9][0-9])_([0-9][0-9])\.blp[\t, ]+(.+)$");

            clsArea area = null;
            while (sr.Peek() != -1)
            {
                string line = sr.ReadLine();

                if (line.StartsWith("dir: "))
                {
                    if (area != null)
                    {
                        int count = 0;
                        for (int x = 0; x < 64; x++)
                            for (int y = 0; y < 64; y++)
                                if (area.minimaps[x, y] != null)
                                    count++;

                    }

                    // Check if its a zone map, or an indoor map
                    System.Diagnostics.Debug.WriteLine(line);
                    if (line.IndexOf("\\") == -1)
                    {
                        area = new clsArea();
                        area.area = line.Remove(0, 5);
                        areas.Add(area.area, area);
                    }
                    else
                    {
                        area = null;
                        //string tValue = line.Substring(line.LastIndexOf("\\") + 1);
                        //if (areas.Contains(tValue))
                        //{
                        //    area = new clsArea();
                        //    area.area = tValue;
                        //    areas.Add(area.area, area);
                        //}
                        //else
                        //{
                        //    tValue = line.Substring(line.LastIndexOf("\\") + 1);
                        //}
                    }
                }
                else if (area != null)
                {
                    Match m = map.Match(line);
                    if (m.Success)
                    {
                        int x = int.Parse(m.Groups[1].Value);
                        int y = int.Parse(m.Groups[2].Value);

                        area.minimaps[x, y] = new clsMinimap();
                        area.minimaps[x, y].filename = m.Groups[3].Value;
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("no match " + line);
                    }
                }
            }
        }

        public void BuildAreas()
        {
            int hMPQ = 0;
            int hFile = 0;
            int FileSize = 0;
            int FileRead = 0;

            areas.Clear();

            //WoW.LogLine( "Opening {0}", path + "\\Data\\misc.MPQ");
            //if( SFmpq.SFileOpenArchive( ".\\misc.MPQ", 0, 0, ref hMPQ) == 1)
            if (SFmpq.SFileOpenArchive(".\\minimap.MPQ", 0, 0, ref hMPQ) == 1)
            {
                //WoW.LogLine( "Opening misc.MPQ|textures\\Minimap\\md5translate.trs");
                //if( SFmpq.SFileOpenFileEx( hMPQ, "textures\\Minimap\\md5translate.trs", 0, ref hFile) == 1)
                if (SFmpq.SFileOpenFileEx(hMPQ, "md5translate.trs", 0, ref hFile) == 1)
                {
                    FileSize = SFmpq.SFileGetFileSize(hFile, ref FileSize);

                    byte[] buffer = new byte[FileSize];
                    //WoW.LogLine( "Reading misc.MPQ|textures\\Minimap\\md5translate.trs[{0}]", FileSize);
                    if (SFmpq.SFileReadFile(hFile, buffer, (uint)FileSize, ref FileRead, IntPtr.Zero) == 1)
                    {
                        //WoW.LogLine( "Parsing md5translate.trs");
                        BuildMinimapList(buffer);
                    }
                    else
                    {
                    }

                    SFmpq.SFileCloseFile(hFile);
                }
                else
                {

                }

                SFmpq.SFileCloseArchive(hMPQ);
            }
            else
            {

            }
        }
 
    }
}
